<template>
  <div class="px-[24px] pt-[32px]" v-show="model">
    <div class="flex items-center justify-between">
      <div class="cursor-pointer">
        <button class="text-black text-xl" @click="back">
          <span class="iconfont icon-return_icon"></span>
        </button>
        <span class="text-black text-lg font-medium ml-[16px] text-[16px]">{{
          $t('message.customsAdd')
        }}</span>
      </div>
      <button
        class="bg-blue-500 text-white px-4 py-1 rounded-md text-sm"
        @click="submitForm(formRef)"
      >
        {{ $t('message.done') }}
      </button>
    </div>

    <div class="pt-[28px]">
      <div class="relative mb-[16px]">
        <div
          class="absolute left-3 top-[22px] transform -translate-y-1/2"
          :class="{
            'text-gray-500': !errorMessageVisible,
            'text-red-500': errorMessageVisible,
          }"
        >
          <span class="icons iconfont icon-link_icon"></span>
        </div>
        <textarea
          v-model="formData.target"
          :placeholder="$t('message.link')"
          class="w-full h-[100px] p-3 pl-[40px] text-sm appearance-none resize-none rounded-lg focus:outline-none"
          :class="{
            'bg-input-bg placeholder-gray-400 text-gray-700':
              !errorMessageVisible,
            'placeholder-red-400 text-red-500 bg-red-50': errorMessageVisible,
          }"
          @blur="handler"
          @focus="focusHandler"
        ></textarea>
        <p
          v-show="errorMessageVisible"
          class="absolute bottom-[-12px] text-red-500 text-xs"
        >
          {{ errorMessage }}
        </p>
      </div>
    </div>
    <div class="relative">
      <div
        class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500"
      >
        <span class="iconfont icon-title_icon"></span>
      </div>
      <input
        v-model="formData.name"
        type="text"
        :placeholder="$t('message.name')"
        class="w-full p-3 pl-[40px] bg-input-bg text-sm rounded-lg placeholder-gray-400 text-gray-700 focus:outline-none"
      />
    </div>

    <div class="w-full pt-[28px]">
      <div
        class="flex justify-between mb-[20px] rounded-[8px] bg-black/20 bg-opacity-20 p-[2px] cursor-pointer"
      >
        <div
          class="h-[28px] leading-[28px] text-center flex-1 truncate rounded-[6px] px-[10px] text-[14px] duration-150"
          :class="
            activeTab === index ? ' bg-white text-custom-black' : 'text-white'
          "
          v-for="(item, index) in tabs"
          :key="item.value"
          @click="activeTab = index"
        >
          {{ item.label }}
        </div>
      </div>
      <div v-show="activeTab === 0">
        <BuiltIcon
          :resources="icons"
          v-model:data="formData.bgImage"
        ></BuiltIcon>
      </div>
      <div v-show="activeTab === 1">
        <ColorCheck
          :bgColor="formData.bgColor"
          :bgText="formData.bgText"
          @changeColor="changeColor"
          @changeText="changeText"
        ></ColorCheck>
      </div>
      <div v-show="activeTab === 2" class="flex flex-col items-center">
        <div
          v-show="formData.bgImage && formData.bgType === 'local'"
          class="icon-img-container relative cursor-pointer w-[60px] h-[60px]"
        >
          <img :src="formData.bgImage" class="" />
          <div
            class="icon-edit flex-center absolute top-0 w-full h-full opacity-0 bg-black/50"
            @click="editImg"
          >
            <span class="iconfont icon-pen_icon text-white"></span>
          </div>
          <div class="absolute top-[-8px] left-[-8px]" @click="deleteImg">
            <span
              class="iconfont icon-close_icon text-[#c7c7cc] rounded-full bg-white p-[4px] font-bold text-[12px]"
            ></span>
          </div>
        </div>
        <div
          v-show="!(formData.bgImage && formData.bgType === 'local')"
          class="inline-block h-[60px] w-[60px] rounded-[16px] text-center leading-[60px] bg-black/5 text-color-t3 cursor-pointer"
          @click="uploadImg"
        >
          <!-- <span class="text-[40px] font-thin">+</span> -->
          <span class="iconfont icon-plus_large_icon text-[24px]"></span>
        </div>
        <p class="pt-[12px] text-center text-[12px] text-color-t3">
          上传本地图标
        </p>
        <input
          class="hidden"
          type="file"
          accept="image/*"
          ref="imgReader"
          @change="loadingImg"
        />
      </div>
    </div>
    <Teleport to="#app">
      <ClipImage
        v-on-click-outside="closeModal"
        ref="clipImageRef"
        v-show="visibleClipImage"
        @close="visibleClipImage = false"
        @confirm="confirmImg"
        @operate="operateImg"
      ></ClipImage>
    </Teleport>
  </div>
</template>
<script setup lang="ts">
import {
  ref,
  reactive,
  getCurrentInstance,
  watchEffect,
  watch,
  Ref,
} from 'vue';
import type { FormInstance } from 'element-plus';
import { ElMessage } from 'element-plus';
import { vOnClickOutside } from '@vueuse/components';
import Cropper from 'cropperjs';
import BuiltIcon from './BuiltIcon.vue';
import ColorCheck from './ColorCheck.vue';
import ClipImage from './ClipImage.vue';
import fileApi from '../api/file';
import settingApi from '../api/setting';
import resourceApi, { LinkItem } from '../api/resource';

const formRef = ref<FormInstance>();
const linkData = ref<LinkItem>({
  name: '',
  target: '',
  bgType: '',
  bgImage: '',
  bgColor: '',
  type: '',
  origin: '',
  bgText: '',
});
let formData = ref<LinkItem>({ ...linkData.value });

const model = defineModel();
const data = defineModel<LinkItem>('data');

const icons = ref([]);
function getResourceByTab(type) {
  return new Promise((resolve) => {
    resourceApi.getPage({ type }).then((res) => {
      resolve(res);
    });
  });
}
getResourceByTab('icon_details').then((res: any) => {
  icons.value = res.records.map((item) => ({
    url: item.target,
    name: item.name,
  }));
});

const { proxy } = getCurrentInstance();
const errorMessage = ref('');
const errorMessageVisible = ref(false);

const handler = () => {
  const f = formData.value;
  f.target = f.target.trim();
  if (!f.target) {
    errorMessage.value = proxy.$t('message.requiredValidURLAddr');
    errorMessageVisible.value = true;
    return false;
  }
  const urlRegex =
    /^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;
  if (!urlRegex.test(f.target)) {
    errorMessage.value = proxy.$t('message.requiredValidURLAddr');
    errorMessageVisible.value = true;
    return false;
  }
  errorMessageVisible.value = false;
  errorMessage.value = '';
  return true;
};

const focusHandler = () => {
  errorMessageVisible.value = false;
};

const resetTip = () => {
  errorMessageVisible.value = false;
  errorMessage.value = '';
};

const tabs = reactive([
  {
    label: '系统内置',
    value: 'system',
  },
  {
    label: '纯色图标',
    value: 'color',
  },
  {
    label: '本地上传',
    value: 'local',
  },
]);

const activeTab = ref(0);

const props = defineProps(['optType']);

watch(
  () => data.value,
  (val) => {
    if (val) {
      formData.value = { ...val };
      const i = tabs.findIndex((item) => item.value === formData.value.bgType);
      activeTab.value = i === -1 ? 0 : i;
    }
  }
);

watchEffect(() => {
  if (!model.value) {
    resetTip();
  }
});

const emits = defineEmits(['submit', 'back']);
const submitForm = (formEl: FormInstance | undefined) => {
  const bool = handler();
  const f = formData.value;
  if (bool) {
    if (f.bgType === 'local' && !f.bgImage) {
      ElMessage({
        message: '请上传本地图标',
        type: 'error',
        plain: true,
      });
      return false;
    } else if (f.bgType === 'system' && !f.bgImage) {
      ElMessage({
        message: '请选择图标',
        type: 'error',
        plain: true,
      });
      return false;
    }
    emits('submit', formData.value);
  }
};

const back = () => {
  emits('back');
};

watchEffect(() => {
  formData.value.bgType = tabs[activeTab.value].value;
});

const changeColor = (color) => {
  formData.value.bgColor = color;
};

const changeText = (text) => {
  formData.value.bgText = text;
};

const visibleClipImage = ref(false);

const closeModal = () => {
  visibleClipImage.value = false;
};

let CROPPER; //创建一个cropper的全局对象
const imgReader = ref<HTMLElement | null>(null);

const uploadImg = () => {
  imgReader.value?.click();
};
const deleteImg = () => {
  formData.value.bgImage = '';
};
const clipImageRef = ref<InstanceType<typeof ClipImage> | null>(null);
const loadingImg = (event) => {
  //读取上传文件
  let reader = new FileReader();
  if (event.target.files[0]) {
    //readAsDataURL方法可以将File对象转化为data:URL格式的字符串（base64编码）
    reader.readAsDataURL(event.target.files[0]);
    reader.onload = (e) => {
      visibleClipImage.value = true;
      let dataURL = reader.result;
      //将img的src改为刚上传的文件的转换格式
      const cropImg = clipImageRef.value.img as HTMLImageElement | undefined;
      if (cropImg) {
        cropImg.src = dataURL as string;
        if (CROPPER) {
          // CROPPER.destroy();
          CROPPER.replace(dataURL as string);
        } else {
          // 创建新的 Cropper 实例
          CROPPER = new Cropper(cropImg, {
            aspectRatio: 16 / 16,
            viewMode: 0,
            dragMode: 'move',
          });
        }
      }
    };
  }
  event.target.value = '';
};

const editImg = () => {
  visibleClipImage.value = true;
  let dataURL = formData.value.bgImage;
  //将img的src改为刚上传的文件的转换格式
  const cropImg = clipImageRef.value.img as HTMLImageElement | undefined;
  if (cropImg) {
    cropImg.src = dataURL as string;
    if (CROPPER) {
      // CROPPER.destroy();
      CROPPER.replace(dataURL as string);
    } else {
      // 创建新的 Cropper 实例
      CROPPER = new Cropper(cropImg, {
        aspectRatio: 16 / 16,
        viewMode: 0,
        dragMode: 'move',
      });
    }
  }
};
const updateSetting = (data) => {
  formData.value.bgImage = data;
  formData.value.bgType = 'local';
};
const confirmImg = () => {
  CROPPER.getCroppedCanvas({
    width: 60,
    height: 60,
    fillColor: '#fff',
    imageSmoothingEnabled: false,
    imageSmoothingQuality: 'high',
  }).toBlob((blob) => {
    const formData = new FormData();
    formData.append('file', blob);
    fileApi
      .fileUploadLocalReturnUrl(formData)
      .then((response) => {
        // 更新个人头像信息
        // props.info.avatar = response;
        updateSetting(response);
        closeModal();
      })
      .catch((err) => {
        console.log(err);
      });
  });
};

const operateImg = (type) => {
  switch (type) {
    case 'leftRotate':
      CROPPER.rotate(-90);
      break;
    case 'rightRotate':
      CROPPER.rotate(90);
      break;
    case 'shrink':
      CROPPER.zoom(-0.1);
      break;
    case 'enlarge':
      CROPPER.zoom(0.1);
      break;
    case 'reset':
      CROPPER.reset();
      break;
  }
};
</script>
<style scoped lang="scss">
.icon-img-container {
  img {
    border-radius: 16px;
  }
  &:hover {
    .icon-edit {
      border-radius: 16px;
      opacity: 1;
    }
  }
}
</style>
